#include "sessionfriendarea.h"
#include"model/data.h"
#include"./mainwidget.h"
#include"model/datacenter.h"



#include<QScrollBar>
#include<QVBoxLayout>
#include<QPushbutton>
#include<QLabel>
#include"debug.h"
#include<QStyleOption>
#include<QPainter>
#include<QList>


SessionFriendArea::SessionFriendArea(QWidget *parent)
    :QScrollArea {parent}
{
    //1.设置必要的属性
    //设置了这个属性，才能够开启滚动效果
    this->setWidgetResizable(true);
    //设置滚动条相关样式
    this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 2px; background-color: rgb(46,46,46);}");
    this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height: 0px; }");
    this->setStyleSheet("QWidget {border: none};");

    //2.把widget创建出来
    container = new QWidget();
    container->setFixedWidth(310);
    this->setWidget(container);

    //给这个widget指定布局管理器，以便后续添加元素
    QVBoxLayout* layout = new QVBoxLayout();
    layout->setContentsMargins(0,0,0,0);
    layout->setSpacing(0);
    layout->setAlignment(Qt::AlignTop);
    container->setLayout(layout);

    //构造一些临时数据，用来作为"界面调试"的依据，后续需要清理
    //通过宏，完成测试代码的裁剪管理
#if TEST_UI
    QIcon icon(":/resource/image/defaultAvatar.png");
    for(int i = 0;i < 30;i++){
        this->addItem(FriendItemType,QString::number(i),icon,"张三" + QString::number(i),"最后一条消息" + QString::number(i));
    }
#endif
}

//根据添加的itemType不同，添加不同类型itemType

void SessionFriendArea::addItem(ItemType itemType, const QString& id, const QIcon &avatar, const QString& name, const QString& text)
{
    SessionFriendItem* item = nullptr;

    if(itemType == SessionItemType){
        item = new SessionItem(this,id,avatar,name,text);
    }
    else if(itemType == FriendItemType)
    {
        item = new FriendItem(this,id,avatar,name,text);
    }
    else if(itemType == ApplyItemType)
    {
        item = new ApplyItem(this,id,avatar,name);
    }
    else
    {
        LOG() << "错误的 ItemType! itemType=" << itemType;
        return ;
    }
    container->layout()->addWidget(item);
}

void SessionFriendArea::clear()
{
    QLayout* layout = container->layout();
    //遍历布局管理器中的所有元素，并以此从布局管理器中删除掉
    for(int i = layout->count() - 1;i >= 0;--i){
        //takeAt移除对应下标元素
        QLayoutItem* item = layout->takeAt(i);
        //释放对象
        if(item->widget()){
            //把这个删除内容的widget进行释放
            //正常使用的时候，new出来的对象添加到布局管理器的....
            delete item->widget();
        }
    }
}

void SessionFriendArea::clickItem(int index)
{
    if(index < 0 || index >= container->layout()->count()){
        LOG() << "点击元素的下标超出范围！index=" << index;
        return ;
    }
    QLayoutItem* layoutItem = container->layout()->itemAt(index);
    if(layoutItem == nullptr || layoutItem->widget() == nullptr){
        LOG() << "指定的元素不存在！index=" << index;
        return ;
    }
    SessionFriendItem* item = dynamic_cast<SessionFriendItem*>(layoutItem->widget());
    item->select();
}

SessionFriendItem::SessionFriendItem(QWidget *owner, const QIcon &avatar, const QString &name, const QString &text)
    :owner(owner)
{

    this->setFixedHeight(70);
    this->setStyleSheet("QWidget {background-color: rgb(231,231,231);}");

    //创建布局管理器
    QGridLayout* layout = new QGridLayout();
    layout->setContentsMargins(20,0,0,0);
    layout->setSpacing(10);
    this->setLayout(layout);

    //消息头像
    QPushButton* avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(50,50);
    avatarBtn->setIconSize(QSize(50,50));
    avatarBtn->setIcon(avatar);
    avatarBtn->setStyleSheet("QPushButton {border: none;}");
    avatarBtn->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);

    //消息名字
    QLabel* nameLabel = new QLabel();
    nameLabel->setText(name);
    nameLabel->setStyleSheet("QLabel{ font-size: 18px; font-weight: 600; }");
    nameLabel->setFixedHeight(35);
    nameLabel->setSizePolicy(QSizePolicy::Expanding , QSizePolicy::Fixed);

    //消息预览
    messageLabel = new QLabel();
    messageLabel->setText(text);
    messageLabel->setFixedHeight(35);
    messageLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);

    //将相关信息添加到布局管理器中
    layout->addWidget(avatarBtn,0,0,2,2);
    //这里将占的列数稍微大点，方便后面其他件的调整
    layout->addWidget(nameLabel,0,2,1,8);
    layout->addWidget(messageLabel,1,2,1,8);

}

void SessionFriendItem::paintEvent(QPaintEvent *event)
{
    //查阅文档，拷贝下面代码
    (void) event;
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget,&opt,&p,this);
}

void SessionFriendItem::mousePressEvent(QMouseEvent *event)
{
    (void)event;
    select();
}

void SessionFriendItem::select()
{
    //鼠标点击时会触发这个函数
    //拿到所有的兄弟元素,还原其他item的背景色
    const QObjectList children = this->parentWidget()->children();
    for(QObject* child : children){
        if(!child->isWidgetType()){
            continue;
        }

        SessionFriendItem* item = dynamic_cast<SessionFriendItem*>(child);
        if(item->selected){
            item->selected = false;
            item->setStyleSheet("QWidget { background-color: rgb(231,231,231);}");
        }
    }

    //点击时，修改背景色,以及选中状态
    this->setStyleSheet("QWidget {background-color: rgb(210,210,210); }");
    this->selected = true;

    //调用active
    this->active();
}

void SessionFriendItem::enterEvent(QEnterEvent *event)
{
    (void)event;
    //如果当前item是选中状态，则不应该受此函数逻辑影响
    if(!this->selected){
        this->setStyleSheet("QWidget { background-color: rgb(215,215,215);}");
    }
}

void SessionFriendItem::leaveEvent(QEvent *event)
{
    //如果当前item是选中状态，则不应该受此函数逻辑影响
    (void)event;
    if(!this->selected){
        this->setStyleSheet("QWidget { background-color: rgb(231,231,231);}");
    }
}

void SessionFriendItem::active()
{
   //父类的active不需要处理任何业务
}


//////////////////////////////////////////////////
////// 会话Item的实现
//////////////////////////////////////////////////

SessionItem::SessionItem(QWidget *owner, const QString &chatSessionId, const QIcon &avatar, const QString &name, const QString &lastMessage)
    :SessionFriendItem(owner,avatar,name,lastMessage)
    ,chatSessionId(chatSessionId)
{
    //处理更新最后一条消息的信号
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    connect(dataCenter,&model::DataCenter::updateLastMessage,this,&SessionItem::updateLastMessage);

    //需要显示未读消息的数目,为了支持客户端重启之后，未读消息还能正确显示
    int unread = dataCenter->getUnread(chatSessionId);
    if(unread > 0){
        //存在未读消息
        this->messageLabel->setText(QString("[未条消息%1条]").arg(unread) + lastMessage);
    }

}

void SessionItem::active()
{
    //点击之后要加载会话的历史消息列表
    LOG()<<"点击SessionItem出发的逻辑！chatSessionId=" << chatSessionId;

    //加载会话历史消息，会涉及当前内存的数据操作、网络通信、界面变更，
    //所以详细内容交给mainwidget处理
    MainWidget* mainWidget = MainWidget::getInstance();
    mainWidget->loadRecentMessage(chatSessionId);

    //清空未读消息的数据，并更新显示
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->clearUnread(chatSessionId);

    //更新界面的显示,把会话消息预览这里前面的"[未读消息x条]"内容干掉
    QString text = this->messageLabel->text();
    int pos = text.toStdString().rfind("]");
    this->messageLabel->setText(QString::fromStdString((text.toStdString().substr(pos + 1))));

}

void SessionItem::updateLastMessage(const QString &chatSessionId)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    //1.判定chatSessionId是否匹配
    //每一个会话item都会和这个信号处理函数绑定
    if(this->chatSessionId != chatSessionId){
        //当前SessionItem不是你正在发送消息的SessionItem
        return;
    }
    //chatSessionId匹配，真正更新最后一条消息!

    //2.把最后一条消息，获取到
    QList<model::Message>* messageList = dataCenter->getRecentMessageList(chatSessionId);
    if(messageList == nullptr || messageList->size() == 0){
        //当前会话没有消息，无需更新
        return ;
    }

    const model::Message& lastMessage = messageList->back();

    //3.明确显示的文本内容
    QString text;
    if(lastMessage.messageType == model::TEXT_TYPE){
        text = lastMessage.content;
    }else if(lastMessage.messageType == model::IMAGE_TYPE){
        text = "[图片]";
    }else if(lastMessage.messageType == model::FILE_TYPE){
        text = "[文件]";
    }else if(lastMessage.messageType == model::SPEECH_TYPE){
        text = "[语音]";
    }else{
        LOG() << "错误的消息类型";
        return ;
    }

    //4.把这个内容显示到会话上
    //先判定当前消息的会话，是不是正在选中的会话，如果是，不会更新任何的未读消息
    //如果不是，看未读消息是否>0,并且做出前缀的拼装
    if(chatSessionId == dataCenter->getCurrentChatSessionId()){
        this->messageLabel->setText(text);
    }else{
        int unread = dataCenter->getUnread(chatSessionId);
        if(unread > 0){
            this->messageLabel->setText(QString("[未读%1条]").arg(unread) + text);
        }
    }

}

//////////////////////////////////////////////////
////// 好友Item的实现
//////////////////////////////////////////////////

FriendItem::FriendItem(QWidget *owner, const QString &userId, const QIcon &avatar, const QString &name, const QString &description)
    :SessionFriendItem(owner,avatar,name,description)
    ,userId(userId)
{

}

void FriendItem::active()
{
    //点击之后，要激活对应的会话列表元素
    LOG() << "点击FriendItem出发的逻辑！userId=" << userId;

    MainWidget* mainWidget = MainWidget::getInstance();
    mainWidget->switchSession(userId);

}

//////////////////////////////////////////////////
////// 好友申请Item的实现
//////////////////////////////////////////////////

ApplyItem::ApplyItem(QWidget *owner, const QString &userId, const QIcon &avatar, const QString &name)
    :SessionFriendItem(owner,avatar,name,"")
    ,userId(userId)
{
    //1.移除父类的messageLabel
    QGridLayout* layout = dynamic_cast<QGridLayout*>(this->layout());
    layout->removeWidget(messageLabel);
    //释放内存
    delete messageLabel;

    //2.添加两个按键
    QPushButton* acceptBtn = new QPushButton();
    acceptBtn->setText("同意");
    QPushButton* rejectBtn = new QPushButton();
    rejectBtn->setText("拒绝");

    //3.添加到布局管理器中
    layout->addWidget(acceptBtn,1,2,1,1);
    layout->addWidget(rejectBtn,1,3,1,1);

    //4.添加信号槽
    connect(acceptBtn,&QPushButton::clicked,this,&ApplyItem::acceptFriendApply);
    connect(rejectBtn,&QPushButton::clicked,this,&ApplyItem::rejectFriendApply);

}

void ApplyItem::acceptFriendApply()
{
    //发送网络请求，告知服务器,同意了
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    //同意谁的好友申请
    //针对这个操作，信号处理，是需要更新好友列表以及好友申请列表，直接在主窗口中处理更合数
    dataCenter->acceptFriendApplyAsync(this->userId);
}

void ApplyItem::rejectFriendApply()
{
    //发送网络请求，告知服务器,拒绝了
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->rejectFriendApplyAsync(this->userId);
}

void ApplyItem::active()
{
    //不需要处理业务
    LOG() << "点击ApplyItem 触发的逻辑！userId=" << userId;
}
